package com.example.coroutines

import kotlinx.coroutines.*
import org.junit.Test
import java.lang.Math.log
import kotlin.concurrent.thread
import kotlin.coroutines.Continuation
import kotlin.coroutines.ContinuationInterceptor
import kotlin.coroutines.CoroutineContext


/**
 * 测试协程拦截器
 *
 * @author zhouronghua
 * @time 2021/12/26 9:23 下午
 */
public class TestInterception {

    @Test
    fun main() {
        runBlocking() {
            testInterceptor()
            delay(2000)
        }
    }


    suspend fun testInterceptor() {
        println(1)

        val job = GlobalScope.launch(
            // 设置上下文(因为KEY相同，后添加的拦截器会覆盖前面的拦截器)
            // Key值不同的话
            context = CoroutineName("MyWorld") + MyNewContinuationInterceptor1() + MyNewContinuationInterceptor2(),
            start = CoroutineStart.UNDISPATCHED
        ) {
            println(2)
            delay(500)
            println(3)
            println("testInterceptor: " + coroutineContext[ContinuationInterceptor])
        }
        println(4)

        job.start()

        println(5)
    }


    private class MyNewContinuationInterceptor1 : ContinuationInterceptor {
        // 情形1：两个拦截器Key相同，后添加的拦截器优先
//        override val key: CoroutineContext.Key<*> = ContinuationInterceptor

        // 情形2：两个拦截器Key不相同，后添加的拦截器优先
        companion object Key : CoroutineContext.Key<MyNewContinuationInterceptor1>
        override val key: CoroutineContext.Key<*> = MyNewContinuationInterceptor1

        override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
            return object : Continuation<T> {
                override val context: CoroutineContext = continuation.context

                override fun resumeWith(result: Result<T>) {
                    println("<MyNewContinuationInterceptor1> $result")
                    thread {
                        continuation.resumeWith(result)
                    }
                }
            }
        }
    }

    private class MyNewContinuationInterceptor2 : ContinuationInterceptor {
        // 情形1：两个拦截器Key相同，后添加的拦截器优先
//        override val key: CoroutineContext.Key<*> = ContinuationInterceptor

        // 情形2：两个拦截器Key不相同，后添加的拦截器优先
        companion object Key : CoroutineContext.Key<MyNewContinuationInterceptor2>
        override val key: CoroutineContext.Key<*> = MyNewContinuationInterceptor2

        override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
            return object : Continuation<T> {
                override val context: CoroutineContext = continuation.context

                override fun resumeWith(result: Result<T>) {
                    println("<MyNewContinuationInterceptor2> $result")
                    thread {
                        continuation.resumeWith(result)
                    }
                }
            }
        }
    }
}
